#include"ThreadSafeQueue.h"

template<class T, class Container>
bool ThreadSafeQueue<T, Container>::push(T&& element) {
	std::unique_lock<std::mutex>lock(mutex_);
	bool flag = queue_->push(std::forward<T>(element));
	if (flag) {
		not_empty_cv_.notify_one();
	}
	return flag;
}

template<class T, class Container>
bool ThreadSafeQueue<T, Container>::push(T& element) {
	std::unique_lock<std::mutex>lock(mutex_);
	bool flag = queue_->push(std::forward<T>(element));
	if (flag) {
		not_empty_cv_.notify_one();
	}
	return flag;
}

template<class T, class Container>
bool ThreadSafeQueue<T, Container>::waitAndPop(T& t) {
	std::unique_lock<std::mutex>lock(mutex_);
	not_empty_cv_.wait(lock, []() {return !queue_->empty(); });
	bool flag = queue_->pop(t);
	return flag;
}

template<class T, class Container>
template<typename Duration>
bool ThreadSafeQueue<T, Container>::waitAndPop(T& t, const Duration& duration_) {
	std::unique_lock<std::mutex>lock(mutex_);
	bool flag = false;
	if (not_empty_cv_.wait_for(lock, duration_, []() {return !queue_->empty(); })) {
		bool flag = queue_->pop(t);
	}
	return flag;
}

template<class T, class Container>
bool ThreadSafeQueue<T, Container>::tryPop(T& t) {
	if (queue_->empty())
		return false;

	std::lock_guard<std::mutex>guard(mutex_);
	bool flag = false;
	if (!queue_->empty()) {
		flag = queue_->pop(t);
	}
	return flag;
}

template<class T, class Container>
bool ThreadSafeQueue<T, Container>::isEmpty()const {
	//std::lock_guard<std::mutex>guard(mutex_);
	return queue_->empty();
}

template<class T, class Container>
bool ThreadSafeQueue<T, Container>::isFull()const {
	return queue_->full();
}